/*
 TUIO C++ Library - part of the reacTIVision project
 http://reactivision.sourceforge.net/
 
 Copyright (c) 2005-2009 Martin Kaltenbrunner <martin@tuio.org>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "TuioContainer.h"
using namespace TUIO;

TuioContainer::TuioContainer (TuioTime ttime, long si, float xp, float yp):TuioPoint(ttime, xp,yp)
,state(TUIO_ADDED)
,source_id(0)
,source_name("undefined")
,source_addr("localhost")
{
	session_id = si;
	x_speed = 0.0f;
	y_speed = 0.0f;
	motion_speed = 0.0f;
	motion_accel = 0.0f;			
	TuioPoint p(currentTime,xpos,ypos);
	path.push_back(p);
	
}

TuioContainer::TuioContainer (long si, float xp, float yp):TuioPoint(xp,yp)
,state(TUIO_ADDED)
,source_id(0)
,source_name("undefined")
,source_addr("localhost")		
{
	session_id = si;
	x_speed = 0.0f;
	y_speed = 0.0f;
	motion_speed = 0.0f;
	motion_accel = 0.0f;			
	TuioPoint p(currentTime,xpos,ypos);
	path.push_back(p);
}

TuioContainer::TuioContainer (TuioContainer *tcon):TuioPoint(tcon)
,state(TUIO_ADDED)
,source_id(0)
,source_name("undefined")
,source_addr("localhost")		
{
	session_id = tcon->getSessionID();
	x_speed = 0.0f;
	y_speed = 0.0f;
	motion_speed = 0.0f;
	motion_accel = 0.0f;
	TuioPoint p(currentTime,xpos,ypos);
	path.push_back(p);
}

void TuioContainer::setTuioSource(int src_id, const char *src_name, const char *src_addr) {
	source_id = src_id;
	source_name = std::string(src_name);
	source_addr = std::string(src_addr);
}

const char* TuioContainer::getTuioSourceName() const{
	return source_name.c_str();
}

const char* TuioContainer::getTuioSourceAddress() const{
	return source_addr.c_str();
}

int TuioContainer::getTuioSourceID() const{
	return source_id;
}

void TuioContainer::update (TuioTime ttime, float xp, float yp) {
	TuioPoint lastPoint = path.back();
	TuioPoint::update(ttime,xp, yp);
	
	TuioTime diffTime = currentTime - lastPoint.getTuioTime();
	float dt = diffTime.getTotalMilliseconds()/1000.0f;
	float dx = xpos - lastPoint.getX();
	float dy = ypos - lastPoint.getY();
	float dist = sqrt(dx*dx+dy*dy);
	float last_motion_speed = motion_speed;
	
	x_speed = dx/dt;
	y_speed = dy/dt;
	motion_speed = dist/dt;
	motion_accel = (motion_speed - last_motion_speed)/dt;
	
	TuioPoint p(currentTime,xpos,ypos);
	path.push_back(p);
	
	if (motion_accel>0) state = TUIO_ACCELERATING;
	else if (motion_accel<0) state = TUIO_DECELERATING;
	else state = TUIO_STOPPED;
}

void TuioContainer::stop(TuioTime ttime) {
	update(ttime,xpos,ypos);
}

void TuioContainer::update (TuioTime ttime, float xp, float yp, float xs, float ys, float ma) {
	TuioPoint::update(ttime,xp, yp);
	x_speed = xs;
	y_speed = ys;
	motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
	motion_accel = ma;
	
	TuioPoint p(currentTime,xpos,ypos);
	path.push_back(p);
	
	if (motion_accel>0) state = TUIO_ACCELERATING;
	else if (motion_accel<0) state = TUIO_DECELERATING;
	else state = TUIO_STOPPED;
}

void TuioContainer::update (float xp, float yp, float xs, float ys, float ma) {
	TuioPoint::update(xp,yp);
	x_speed = xs;
	y_speed = ys;
	motion_speed = (float)sqrt(x_speed*x_speed+y_speed*y_speed);
	motion_accel = ma;
	
	path.pop_back();
	TuioPoint p(currentTime,xpos,ypos);
	path.push_back(p);
	
	if (motion_accel>0) state = TUIO_ACCELERATING;
	else if (motion_accel<0) state = TUIO_DECELERATING;
	else state = TUIO_STOPPED;
}

void TuioContainer::update (TuioContainer *tcon) {
	TuioPoint::update(tcon);
	x_speed = tcon->getXSpeed();
	y_speed =  tcon->getYSpeed();
	motion_speed =  tcon->getMotionSpeed();
	motion_accel = tcon->getMotionAccel();
	
	TuioPoint p(tcon->getTuioTime(),xpos,ypos);
	path.push_back(p);
	
	if (motion_accel>0) state = TUIO_ACCELERATING;
	else if (motion_accel<0) state = TUIO_DECELERATING;
	else state = TUIO_STOPPED;
}

void TuioContainer::remove(TuioTime ttime) {
	currentTime = ttime;
	state = TUIO_REMOVED;
}

long TuioContainer::getSessionID() const{ 
	return session_id;
}

void TuioContainer::setSessionID(long s_id) { 
	session_id = s_id;
}

float TuioContainer::getXSpeed() const{ 
	return x_speed;
}

float TuioContainer::getYSpeed() const{ 
	return y_speed;
}

TuioPoint TuioContainer::getPosition() const{
	TuioPoint p(xpos,ypos);
	return p;
}

std::list<TuioPoint> TuioContainer::getPath() const{
	return path;
}

float TuioContainer::getMotionSpeed() const{
	return motion_speed;
}

float TuioContainer::getMotionAccel() const{
	return motion_accel;
}

int TuioContainer::getTuioState() const{ 
	return state;
}	

bool TuioContainer::isMoving() const{ 
	if ((state==TUIO_ACCELERATING) || (state==TUIO_DECELERATING)) return true;
	else return false;
}

